Imports System.Configuration.Provider
Imports System.Web


Public MustInherit Class QuestionnaireTakerProvider
    Inherits ProviderBase

    Friend ReadOnly _lock As New Object
    Private _childNodeCollectionTable As Hashtable
    Private _firstNodeTable As Hashtable
    Private _keyTable As Hashtable
    Private _instrumentNodeTable As Hashtable



    Protected Sub New()
    End Sub

    ' Properties
    Public MustOverride Property ApplicationName() As String

    Friend ReadOnly Property ChildNodeCollectionTable() As IDictionary
        Get
            If (Me._childNodeCollectionTable Is Nothing) Then
                SyncLock _lock
                    If (Me._childNodeCollectionTable Is Nothing) Then
                        Me._childNodeCollectionTable = New Hashtable
                    End If
                End SyncLock
            End If
            Return Me._childNodeCollectionTable
        End Get
    End Property

    Friend ReadOnly Property FirstNodeTable() As IDictionary
        Get
            If (Me._firstNodeTable Is Nothing) Then
                SyncLock _lock
                    If (Me._firstNodeTable Is Nothing) Then
                        Me._firstNodeTable = New Hashtable
                    End If
                End SyncLock
            End If
            Return Me._firstNodeTable
        End Get
    End Property

    Friend ReadOnly Property KeyTable() As IDictionary
        Get
            If (Me._keyTable Is Nothing) Then
                SyncLock _lock
                    If (Me._keyTable Is Nothing) Then
                        Me._keyTable = New Hashtable
                    End If
                End SyncLock
            End If
            Return Me._keyTable
        End Get
    End Property

    Friend ReadOnly Property InstrumentNodeTable() As IDictionary
        Get
            If (Me._instrumentNodeTable Is Nothing) Then
                SyncLock _lock
                    If (Me._instrumentNodeTable Is Nothing) Then
                        Me._instrumentNodeTable = New Hashtable
                    End If
                End SyncLock
            End If
            Return Me._instrumentNodeTable
        End Get
    End Property

    Protected Friend Sub AddNode(ByRef iNode As InstrumentNode, _
    ByVal node As IQuestionNode, ByVal parentNode As IQuestionNode)
        If (node Is Nothing) Then
            Throw New ArgumentNullException("node")
        End If
        SyncLock _lock
            If Me.KeyTable.Contains(node.UID) Then
                Throw New InvalidOperationException("a duplicated key is founded: " & node.UID.ToString)
            End If
            Me.KeyTable.Item(node.UID) = node
            If (parentNode Is Nothing) Then
                iNode.Questions.Add(node)
                Exit Sub
            End If
            If (Me.ChildNodeCollectionTable.Item(parentNode) Is Nothing) Then
                Me.ChildNodeCollectionTable.Item(parentNode) = New IQuestionNodeCollection
            End If
            CType(Me.ChildNodeCollectionTable.Item(parentNode), IQuestionNodeCollection).Add(node)
        End SyncLock
    End Sub

    Protected Friend Sub RemoveNode(ByVal node As IQuestionNode)
        If (node Is Nothing) Then
            Throw New ArgumentNullException("node")
        End If
        SyncLock _lock
            Dim parentNode As IQuestionNode = FindNode(node.ParentUID)
            If (Not parentNode Is Nothing) Then
                Dim childNodes As IQuestionNodeCollection = CType(Me.ChildNodeCollectionTable.Item(parentNode), IQuestionNodeCollection)
                If ((Not childNodes Is Nothing) AndAlso childNodes.Contains(node)) Then
                    childNodes.Remove(node)
                End If
            End If
            Dim key As Guid = node.UID
            If Me.KeyTable.Contains(key) Then
                Me.KeyTable.Remove(key)
            End If
        End SyncLock
    End Sub

    Protected Overridable Sub Clear()
        SyncLock _lock
            If (Not Me._childNodeCollectionTable Is Nothing) Then
                Me._childNodeCollectionTable.Clear()
                'Me._childNodeCollectionTable = Nothing
            End If
            If (Not Me._firstNodeTable Is Nothing) Then
                Me._firstNodeTable.Clear()
                'Me._firstNodeTable = Nothing
            End If
            If (Not Me._instrumentNodeTable Is Nothing) Then
                Me._instrumentNodeTable.Clear()
                'Me._questionnaireNodeTable = Nothing
            End If
            If (Not Me._keyTable Is Nothing) Then
                Me._keyTable.Clear()
                'Me._keyTable = Nothing
            End If
        End SyncLock
    End Sub



    Public Function FindNode(ByVal uid As Guid) As IQuestionNode
        If Me.KeyTable.Contains(uid) Then
            Return CType(Me.KeyTable.Item(uid), IQuestionNode)
        End If
        Return Nothing
    End Function

    Public Function GetChildNodes(ByVal iNode As InstrumentNode) As IQuestionNodeCollection
        Return iNode.Questions
    End Function

    Public Function GetChildNodes(ByVal node As IQuestionNode) As IQuestionNodeCollection
        If (node Is Nothing) Then
            Throw New ArgumentNullException("node")
        End If
        Dim childNodes As IQuestionNodeCollection = CType(Me.ChildNodeCollectionTable.Item(node), IQuestionNodeCollection)
        If (childNodes Is Nothing) Then
            Dim node1 As IQuestionNode = CType(Me.KeyTable.Item(node.UID), IQuestionNode)
            If (Not node1 Is Nothing) Then
                childNodes = CType(Me.ChildNodeCollectionTable.Item(node1), IQuestionNodeCollection)
            End If
        End If
        If (childNodes Is Nothing) Then
            Return IQuestionNodeCollection.Empty
        End If
        Return childNodes
    End Function

    Public Function GetParentNode(ByVal node As IQuestionNode) As IQuestionNode
        Return FindNode(node.ParentUID)
    End Function

    Private Function GetSiblingNodes(ByVal node As IQuestionNode) As IQuestionNodeCollection
        Dim parentNode As IQuestionNode = node.ParentNode
        If parentNode Is Nothing Then
            Return BuildInstrumentNode(CType(node, QuestionNode).InstrumentID).Questions
        Else
            Return parentNode.ChildNodes
        End If
    End Function

    Public Function GetNextSibling(ByVal node As IQuestionNode) As IQuestionNode
        Dim Siblings As IQuestionNodeCollection = GetSiblingNodes(node)
        If (Not Siblings Is Nothing) Then
            Dim index As Integer = Siblings.IndexOf(node)
            If ((index >= 0) AndAlso (index < (Siblings.Count - 1))) Then
                Return Siblings.Item((index + 1))
            End If
        End If
        Return Nothing
    End Function

    Public Function GetNextSiblings(ByVal node As IQuestionNode) As IQuestionNodeCollection
        Dim Siblings As IQuestionNodeCollection = GetSiblingNodes(node)
        If (Not Siblings Is Nothing) Then
            Dim nextSiblings As New IQuestionNodeCollection
            Dim index As Integer = Siblings.IndexOf(node) + 1
            For i As Integer = index To Siblings.Count - 1
                nextSiblings.Add(Siblings.Item(i))
            Next
            Return nextSiblings
        End If
        Return Nothing
    End Function

    Public Function GetPreviousSiblings(ByVal node As IQuestionNode) As IQuestionNodeCollection
        Dim Siblings As IQuestionNodeCollection = GetSiblingNodes(node)
        If (Not Siblings Is Nothing) Then
            Dim prevSiblings As New IQuestionNodeCollection
            Dim index As Integer = Siblings.IndexOf(node)
            If index > 0 Then
                For i As Integer = 0 To index - 1
                    prevSiblings.Add(Siblings.Item(i))
                Next
                Return prevSiblings
            End If
        End If
        Return Nothing
    End Function



    Public MustOverride Function BuildQuestionnaireNode(ByVal questionnaireId As Integer) As QuestionnaireNode

    Public MustOverride Function BuildInstrumentNode(ByVal instrumentId As String) As InstrumentNode

    Public MustOverride Sub FillInstrumentDetails(ByRef node As InstrumentNode)

    Public MustOverride Function GetAnswerFromDB( _
        ByVal questionnaireId As Integer, _
        ByVal instrumentId As String, _
        ByVal userName As String) As Hashtable

    Public MustOverride Function GetChoices(ByVal id As Integer) As DataTable

    Public MustOverride Function GetQuestion(ByVal id As Integer) As Question

    Public MustOverride Function GetQuestionnaires() As DataTable

    Public MustOverride Function GetPercentCompletion( _
        ByVal questionnaireId As Integer, _
        ByVal instrumentId As String) As String

    Public MustOverride Sub SetAnswer( _
        ByVal questionnaireId As Integer, _
        ByVal instrumentId As String, _
        ByVal uid As Guid, _
        ByVal answer As String, _
        ByVal status As String)





End Class
